package ch.unifr.diuf.webeng.taskmap.client;

import java.util.Date;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.maps.client.InfoWindow;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.InfoWindowContent.InfoWindowTab;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.geocode.DirectionQueryOptions;
import com.google.gwt.maps.client.geocode.DirectionQueryOptions.TravelMode;
import com.google.gwt.maps.client.geocode.DirectionResults;
import com.google.gwt.maps.client.geocode.Directions;
import com.google.gwt.maps.client.geocode.DirectionsCallback;
import com.google.gwt.maps.client.geocode.DirectionsPanel;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LocationCallback;
import com.google.gwt.maps.client.geocode.Placemark;
import com.google.gwt.maps.client.geocode.StatusCodes;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class Task {
	private static int nextId = 0;
	
	int id;
	String taskTitle = "";
	String taskAddress = "";
	Date taskDate = new Date();
	String taskStartTime = "";
	String taskEndTime = "";
	
	
	private DirectionsPanel directionsPanel;
	
	/**
	 * The empty Task constructor.
	 */
	public Task() {
		nextId++;
		id = nextId;
	}

	/**
	 * The Task constructor.
	 * 
	 * @param title  the title of the task
	 * @param address  the address of the task
	 * @param date  the date of the task
	 * @param startTime  the start time of the task
	 * @param endTime  the end time of the task
	 */
	public Task(String title, String address, Date date, String startTime, String endTime) {
		nextId++;
		id = nextId;
		taskTitle = title;
		taskAddress = address;
		taskDate = date;
		taskStartTime = startTime;
		taskEndTime = endTime;
	}
	
	/**
	 * Gets the id of the task.
	 * 
	 * @return  the id of the task
	 */
	public int getId() {
		return id;
	}
	
	/**
	 * Gets the title of the task.
	 * 
	 * @return  the title of the task
	 */
	public String getTitle() {
		return taskTitle;
	}

	/**
	 * Sets the title of the task.
	 * 
	 * @param title  the title of the task
	 */
	public void setTitle(String title) {
		taskTitle = title;
	}

	/**
	 * Gets the address of the task.
	 * 
	 * @return  the address of the task
	 */
	public String getAddress() {
		return taskAddress;
	}

	/**
	 * Sets the address of the task.
	 * 
	 * @param address  the address of the task
	 */
	public void setAddress(String address) {
		taskAddress = address;
	}

	/**
	 * Gets the date of the task.
	 * 
	 * @return  the date of the task
	 */
	public Date getDate() {
		return taskDate;
	}

	/**
	 * Sets the date of the task.
	 * 
	 * @param date  the date of the task
	 */
	public void setDate(Date date) {
		taskDate = date;
	}

	/**
	 * Gets the start time of the task.
	 * 
	 * @return  the start time of the task
	 */
	public String getStartTime() {
		return taskStartTime;
	}

	/**
	 * Sets the start time of the task.
	 * 
	 * @param startTime  the start time of the task
	 */
	public void setStartTime(String startTime) {
		taskStartTime = startTime;
	}

	/**
	 * Gets the end time of the task.
	 * 
	 * @param endTime  the end time of the task
	 */
	public String getEndTime() {
		return taskEndTime;
	}

	/**
	 * Sets the end time of the task.
	 * 
	 * @param endTime  the end time of the task
	 */
	public void setEndTime(String endTime) {
		taskEndTime = endTime;
	}

	/**
	 * Adds the task to a <code>MapWidget</code> in form of a <code>Marker</code> with an <code>InfoWindowTab</code>.
	 * 
	 * @param map  the MapWidget to which the task is added
	 */
	public void addTaskToMap(final MapWidget map, final boolean openInfoWindow) {
		final String title = this.getTitle();
		final String address = this.getAddress();
		final Date date = this.getDate();
		final String startTime = this.getStartTime();
		final String endTime = this.getEndTime();

		Geocoder geocoder = new Geocoder();
		geocoder.getLocations(address, new LocationCallback() {
			public void onFailure(int statusCode) {
				Window.alert("Sorry, we were unable to geocode that address");
			}
			public void onSuccess(JsArray<Placemark> locations) {
				Placemark place = locations.get(0);
				final Marker marker = new Marker(place.getPoint());
				InfoWindowTab tabs[] = new InfoWindowTab[2];
				String info = "<b>Title:</b> "+title+"<br /><b>Address:</b> "+place.getAddress()+"<br /><b>Date:</b> "+date.toString()+"<br /><b>Start:</b> "+startTime+"<br /><b>End:</b> "+endTime;
				tabs[0] = new InfoWindowTab("Info", info);
				VerticalPanel panel = new VerticalPanel();
				final HorizontalPanel label = new HorizontalPanel();
				final VerticalPanel options = new VerticalPanel();
				HTML directionsLabel = new HTML("<b>Get directions</b>");
				final ListBox dirType = new ListBox();
				dirType.addItem("Driving", "DRIVING");
				dirType.addItem("Walking", "WALKING");
				final HorizontalPanel addressPanel = new HorizontalPanel();
				final HTML startAddressLabel = new HTML("Start address: ");
				final TextBox startAddress = new TextBox();
				addressPanel.add(startAddressLabel);
				addressPanel.add(startAddress);
				final Button directionsButton = new Button("Get directions");
				directionsButton.addClickHandler(new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						directionsPanel = new DirectionsPanel();
						DirectionQueryOptions opts = new DirectionQueryOptions(map, directionsPanel);
						String type = dirType.getValue(dirType.getSelectedIndex());
						opts.setTravelMode(TravelMode.valueOf(type));
						String query = "from: "+startAddress.getText()+" to: "+address+", Switzerland";
						Directions.load(query, opts, new DirectionsCallback() {
							public void onFailure(int statusCode) {
								Window.alert("Failed to load directions: Status "
										+ StatusCodes.getName(statusCode) + " " + statusCode);
							}

							public void onSuccess(final DirectionResults result) {
								dirType.setVisible(false);
								startAddressLabel.setVisible(false);
								startAddress.setVisible(false);
								directionsButton.setVisible(false);
								final Button removeDirections = new Button("Hide directions");
								class RemoveDirHandler implements ClickHandler {
									public void onClick(ClickEvent event) {
										removeDirections.setVisible(false);
										map.getParent().setHeight("500px");
										map.setHeight("100%");
										RootPanel.get("dirTitle").clear();
										RootPanel.get("dirContent").clear();
										map.removeOverlay(result.getPolyline());
										
										for(Marker m : result.getMarkers()) {
											map.removeOverlay(m);
										}
										dirType.setVisible(true);
										startAddressLabel.setVisible(true);
										startAddress.setVisible(true);
										directionsButton.setVisible(true);
									}
								}
								RemoveDirHandler removeDirHandler = new RemoveDirHandler();
								removeDirections.addClickHandler(removeDirHandler);
								options.add(removeDirections);
								VerticalPanel directions = new VerticalPanel();
								HTML directionsTitle = new HTML("<h2>Directions</h2>");
								map.getParent().setHeight("400px");
								map.setHeight("80%");
								RootPanel.get("dirTitle").add(directionsTitle);
								directions.add(directionsPanel);
								RootPanel.get("dirContent").add(directions);
								Button removeDirectionsCopy = new Button("Hide directions");
								removeDirectionsCopy.addClickHandler(removeDirHandler);
								directions.add(removeDirectionsCopy);
							}
						});
					}
				});
				label.add(directionsLabel);
				options.add(dirType);
				options.add(directionsButton);
				panel.add(label);
				panel.add(addressPanel);
				panel.add(options);
				tabs[1] = new InfoWindowTab("Directions", panel);
				final InfoWindowContent content = new InfoWindowContent(tabs, 0);
				marker.addMarkerClickHandler(new MarkerClickHandler() {
					public void onClick(MarkerClickEvent event) {
						InfoWindow info = map.getInfoWindow();
						info.open(marker,content);
					}
				});
				map.addOverlay(marker);
				if(openInfoWindow){
					map.getInfoWindow().open(marker, content);
				}
			}
		});
	}


	/**
	 * Adds the task to a database. Not implemented yet...
	 */
	public void addTaskToDB() {
		// TODO implement method
	}
}
